package org.wattdepot.cli.command;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.resource.property.jaxb.Properties;
import org.wattdepot.resource.property.jaxb.Property;
import org.wattdepot.resource.sensordata.jaxb.SensorData;
import org.wattdepot.resource.source.jaxb.Source;
import org.wattdepot.resource.source.jaxb.SubSources;

/**
 * Contains the abstract class for wattdepot commands.
 * 
 * @author Alex Kan and Kelvin Green
 * @version 2.0
 */
public abstract class WattDepotCommand {

  /**
   * Final string cr represents a new line char for the operating system running the application.
   */
  final String cr = System.getProperty("line.separator");
  /**
   * Final string BAD_FORMAT is display when command is not formatted correctly.
   * 
   */
  static final String BAD_FORMAT = "Command is not properly formatted.";
  /**
   * Final string RES_NOT_FOUND is display when a resource is not found.
   * 
   */
  static final String RES_NOT_FOUND = "The specified source was not found.";

  /**
   * Final string CON_NOT_FOUND is display when a connection to wattdepot server is not found.
   * 
   */
  static final String CON_NOT_FOUND = "No connection to the network found.";

  private static WattDepotClient client = null;

  /**
   * An abstract implementation of the doCommand.
   * 
   * @param args contains an array of strings created from the user input.
   * @return a string with output of method.
   */
  public abstract String doCommand(String args[]);

  /**
   * Static connect method to create connection to WattDepot Service.
   * 
   * @param uri contains a string of the uri to connect to WattDepot.
   * @return a string with output of method.
   */
  public static String connect(String uri) {
    client = new WattDepotClient(uri, null, null);
    // Stop right away if we cannot contact server.
    if (!client.isHealthy()) {
      return "Failed to connect to " + client.getWattDepotUri();
    }
    // Indicate successful connection.
    return "Connected to " + client.getWattDepotUri();
  }

  /**
   * Calls subSources method to get ArrayList of org.wattdepot.resource.source.jaxb.SubSources.
   * 
   * @param source contains a org.wattdepot.resource.source.jaxb.Source object.
   * @return a ArrayList<String> with output of method.
   */
  public List<String> getSubSources(Source source) {
    return subSources(source);
  }

  /**
   * Request a list of SubSources for a specified org.wattdepot.resource.source.jaxb.Source.
   * 
   * @param source contains a org.wattdepot.resource.source.jaxb.Source object.
   * @return a ArrayList<String> with output of method.
   */
  protected List<String> subSources(Source source) {
    boolean error = false;
    ArrayList<String> ssList = new ArrayList<String>();
    try {
      SubSources ss = source.getSubSources();
      List<String> list = ss.getHref();
      ListIterator<String> ssIterator = list.listIterator();
      while (ssIterator.hasNext()) {
        String[] ssName = ssIterator.next().split("/");
        ssList.add(ssName[ssName.length - 1]);
      }
    }
    catch (Exception e) {
      error = true;
      if (error) {
        error = false;
      }
    }
    return ssList;
  }

  /**
   * Calls propertiesList to get properties.
   * @param sensorData holds an instance of a SensorData.
   * @return a String of properties of a Sensordata.
   */
  public String getPropertiesList(SensorData sensorData) {
    return propertiesList(sensorData);
  }

  /**
   * Gets properties of a Sensordata.
   * @param sensorData holds an instance of a SensorData.
   * @return a String of properties of a Sensordata.
   */
  public String propertiesList(SensorData sensorData) {
    String output = "";
    boolean error = false;

    ArrayList<String> propertiesList = new ArrayList<String>();
    try {
      Properties properties = sensorData.getProperties();
      List<Property> propList = properties.getProperty();
      ListIterator<Property> propIterator = propList.listIterator();
      while (propIterator.hasNext()) {
        Property prop = propIterator.next();
        propertiesList.add("(" + prop.getKey() + ": " + Double.parseDouble(prop.getValue())
            / 100000 + ")");
      }
    }
    catch (Exception e) {
      error = true;

      if (error) {
        error = false;
      }
    }
    ArrayList<String> outputArray = new ArrayList<String>();
    ListIterator<String> li = propertiesList.listIterator();
    while (li.hasNext()) {
      outputArray.add(li.next());
    }
    output += outputArray.toString();
    output = output.replace("[", "");
    output = output.replace("]", "");
    return output;
  }

  /**
   * Returns WattDepotCommand client connection.
   * 
   * @return WattDepotCommand instance org.wattdepot.client.WattDepotClient.
   */
  protected WattDepotClient getClient() {
    return client;
  }

}